package com.hy.${packageCode}.shared.autoconfigure.feign;

import com.hy.${packageCode}.shared.exception.DefaultFeignExceptionHandler;
import com.hy.${packageCode}.shared.exception.DefaultFeignExceptionHandler;
import com.hy.${packageCode}.shared.feign.FeignDecoder;
import com.hy.${packageCode}.shared.autoconfigure.common.SharedProperties;
import com.hy.${packageCode}.shared.utils.UserAuditorHelper;
import com.hy.${packageCode}.shared.exception.DefaultFeignExceptionHandler;
import feign.Feign;
import feign.RequestInterceptor;
import feign.codec.Decoder;
import feign.optionals.OptionalDecoder;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.support.HttpMessageConverterCustomizer;
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import java.lang.reflect.Field;

@ConditionalOnClass(value = Decoder.class)
@Configuration
public class FeignAutoConfiguration {

    private static final String X_REQUESTED_WITH = "X-Requested-With";
    private static final String XML_HTTP_REQUEST = "XMLHttpRequest";

    @Bean(name = "feignSsoRequestInterceptor")
    @ConditionalOnMissingBean(name = "feignSsoRequestInterceptor")
    public RequestInterceptor feignSsoRequestInterceptor(SharedProperties sharedProperties) {
        return template -> {
            // 添加AJAX请求标识 302逻辑判断标识
            template.header(X_REQUESTED_WITH, XML_HTTP_REQUEST);
            // 认证信息处理
            UserAuditorHelper.retrieveCurrentToken().ifPresent(token ->
                    template.header(sharedProperties.getToken().getName(), token)
            );
        };
    }

    @Bean
    @ConditionalOnMissingBean(Decoder.class)
    public Decoder feignDecoder(ObjectFactory<HttpMessageConverters> msgConverters,
                                ObjectProvider<HttpMessageConverterCustomizer> customizers) {
        FeignDecoder feignDecoder = new FeignDecoder(
                new SpringDecoder(msgConverters, customizers));
        ResponseEntityDecoder responseEntityDecoder = new ResponseEntityDecoder(feignDecoder);
        return new OptionalDecoder(responseEntityDecoder);
    }

    @Bean
    @ConditionalOnMissingBean(Feign.Builder.class)
    public Feign.Builder feignBuilder(Decoder decoder) throws NoSuchFieldException, IllegalAccessException {
        Feign.Builder builder = Feign.builder().decoder(decoder);
        Field decodeVoid = builder.getClass().getSuperclass().getDeclaredField("decodeVoid");
        decodeVoid.setAccessible(true);
        decodeVoid.set(builder, true);
        return builder;
    }

    @Bean
    @Primary
    @ConditionalOnWebApplication
    public DefaultFeignExceptionHandler defaultExceptionHandler() {
        return new DefaultFeignExceptionHandler();
    }

}
